#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <cstdbool>
#include <unistd.h>
#include "Thread.hpp"
#include "Mutex.hpp"
#include "Conditional.hpp"

namespace YX
{
    const int g_default_size=3;
}

template<class T>
class ThreadPool
{
private:
    int _size; // 线程数量
    std::vector<Thread *> _threads; // 线程数组
    std::queue<T> _taskQueue; // 任务队列
    Mutex _mutex; // 任务队列的互斥锁
    Conditional _cond; // 消费者的条件变量
public:
    ThreadPool(int size=YX::g_default_size):_size(size),_threads(size,nullptr)
    {
        for(int i=0;i<size;++i)
        {
            _threads[i]=new Thread(i+1,routine,(void*)this);
        }
    }

    void Run()
    {
        // 将池中的线程"运行"起来
        for(auto &iter : _threads)
        {
            iter->Create();
            std::cout<<iter->GetName()<<"启动成功"<<std::endl;
        }
    }

    static void *routine(void *args)
    {
        ThreadData *ptd=(ThreadData *)args; // ThreadData指针

        ThreadPool<T> *ptp=(ThreadPool<T> *)ptd->_objThis; // 线程池对应的this指针

        while(true)
        {

            // std::cout<<"queue size:"<<ptp->_taskQueue.size()<<std::endl; // 可以直接通过this指针访问

            // 获取任务
            ptp->_mutex.Lock();
            while(ptp->_taskQueue.empty())
            {
                ptp->_cond.Wait(ptp->_mutex);
            }
            T task = ptp->_taskQueue.front();
            ptp->_taskQueue.pop();
            ptp->_mutex.UnLock();

            // 消费任务
            task(ptd->_name);
            sleep(2);
        }
    }

    void PushTask(const T& task)
    {
        // 生产任务
        _mutex.Lock();
        _taskQueue.push(task);
        _mutex.UnLock();
        _cond.Signal();
        //_cond.BroadCast();
    }

    ~ThreadPool()
    {
        for(auto &iter : _threads)
        {
            iter->Cancel();
            iter->Join();
            delete iter;
        }
    }
};